package cn.vonce.validator.intercept;

import cn.vonce.validator.annotation.VBean;
import cn.vonce.validator.config.EnableValidator;
import cn.vonce.validator.config.ResultConfig;
import cn.vonce.validator.enumerate.ResultCode;
import cn.vonce.validator.enumerate.ResultType;
import cn.vonce.validator.exception.ValidatorException;
import cn.vonce.validator.helper.ValidatorHelper;
import cn.vonce.validator.model.BeanResult;
import cn.vonce.validator.model.FieldResult;
import cn.vonce.validator.utils.RequestDataUtil;
import org.noear.solon.Solon;
import org.noear.solon.core.aspect.Interceptor;
import org.noear.solon.core.aspect.Invocation;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ContextUtil;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

/**
 * 校验字段拦截器
 *
 * @author Jovi
 * @version 1.0
 * @email imjovi@qq.com
 * @date 2025年07月26日02:12
 */
public class ValidatorInterceptor implements Interceptor {

    private final Logger logger = Logger.getLogger(ValidatorInterceptor.class.getName());

    @Override
    public Object doIntercept(Invocation inv) throws Throwable {
        String fullName = inv.method().getMethod().getReturnType().getSimpleName() + " " + inv.getTargetClz().getName() + "." + inv.method().getMethod().getName();
        if (fullName.contains("$$")) {
            return inv.invoke();
        }
        if (inv.args().length == 0) {
            return inv.invoke();
        }
        BeanResult beanResult = new BeanResult(true, "校验通过");
        for (int i = 0; i < inv.args().length; i++) {
            // 获取实际对象-即为原始对象(可能是Bean，也可能是字段)
            Object object = inv.args()[i];
            Annotation[] annotations = inv.method().getMethod().getParameterAnnotations()[i];
            // 优先校验bean
            VBean validBean = ValidatorHelper.getAnnotation(annotations, VBean.class);
            if (validBean != null) {
                beanResult = ValidatorHelper.validBean(object, validBean.group(), validBean.interrupt());
                break;
            }
            // 校验有注解的字段
            List<FieldResult> validFieldResultList = ValidatorHelper.valid(annotations, inv.method().getMethod().getName() + "方法第" + (i + 1) + "个参数", object, null, "", true);
            if (!validFieldResultList.isEmpty()) {
                beanResult = new BeanResult("校验存在" + validFieldResultList.size() + "条错误", validFieldResultList);
                break;
            }
        }
        logger.info("正在校验参数: " + fullName + "[" + ContextUtil.current().uri() + "]");
        Collection<String> collection = ContextUtil.current().paramNames();
        Map<String, String[]> paramsMap = new HashMap<>();
        for (String key : collection) {
            paramsMap.put(key, ContextUtil.current().paramValues(key));
        }
        logger.info("请求URL参数: " + (RequestDataUtil.getParameters(paramsMap)));
        if (!beanResult.isPass()) {
            String tips = beanResult.getFieldResultList().get(0).getTips();
            logger.warning(beanResult.getMessage() + "，详情请看: " + beanResult.getFieldResultList());
            logger.info("参数校验不通过: " + fullName);
            EnableValidator enableValidator = inv.getTargetClz().getAnnotation(EnableValidator.class);
            ResultType resultType;
            if (enableValidator != null) {
                resultType = enableValidator.resultType();
            } else {
                ResultConfig resultConfig = Solon.context().getBean(ResultConfig.class);
                resultType = resultConfig.getResultType();
            }
            if (resultType == null || resultType == ResultType.THROW_TIPS) {
                throw new ValidatorException("参数校验错误[" + tips + "]");
            }
            this.defaultResult(tips, ContextUtil.current().path(), ContextUtil.current());
            return null;
        }
        return inv.invoke();
    }

    /**
     * 默认返回结果
     *
     * @param tips
     * @param path
     * @param current
     */
    private void defaultResult(String tips, String path, Context current) {
        current.charset("UTF-8");
        current.contentType("application/json; charset=utf-8");
        String data = "{\"code\":" + ResultCode.BAD.getCode() + ",\"msg\":\"" + tips + "\"}";
        current.output(data);
        this.logger.info(path + " 的响应内容：" + data);
    }

}
